package com.re6g3y.dl4j.core;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import org.deeplearning4j.gym.StepReply;
import org.deeplearning4j.rl4j.space.Encodable;

public class GameCore extends ApplicationAdapter {
    public Client<Integer,Encodable> client;
    public GameCore(Client client){
        this();
        this.client=client;
    }
    public GameCore() {
        super();
    }

    public OrthographicCamera camera;
    public OrthographicCamera UIcamera;
    public ShapeRenderer shapeRenderer;
    public Box2DDebugRenderer box2DDebugRenderer;
    public boolean viewAble =true;

    public Batch batch;
    public World world;
    private Core core;


    @Override
    public void create () {
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        UIcamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        new InputEven(camera);

        shapeRenderer = new ShapeRenderer();
        shapeRenderer.setAutoShapeType(true);
        box2DDebugRenderer = new Box2DDebugRenderer();
        batch=new SpriteBatch();
        world=new World(new Vector2(0,0),true);

        core=new Core(world,this);
    }

    @Override
    public void resize (int width, int height) {
        float x=camera.position.x;
        float y=camera.position.y;
        float z=camera.position.z;
        camera.setToOrtho(false,width,height);
        camera.position.set(x,y,z);

        x=UIcamera.position.x;
        y=UIcamera.position.y;
        z=UIcamera.position.z;
        UIcamera.setToOrtho(false,width,height);
        UIcamera.position.set(x,y,z);
    }


    public boolean updateWorld(float detTime){

        int index=client.getAction();
        if(client.isReset())core.reset();

        Runnable updatePhyWorld=()-> world.step(detTime, 2, 2);

        StepReply<Encodable> stepReply=core.update(updatePhyWorld,index-1);

        client.setStepReply(stepReply);
        return stepReply.isDone();
    }

    int tick=0;
    @Override
    public void render () {
        super.render();

        if(Gdx.input.isKeyJustPressed(Input.Keys.SPACE)) viewAble =!viewAble;

        float detTime= Math.min(1f/10, Gdx.graphics.getDeltaTime());
//        System.out.println(Gdx.graphics.getDeltaTime());
        detTime=1/10f;

        camera.update();
        if(viewAble) {
            batch.setProjectionMatrix(camera.combined);
            shapeRenderer.setProjectionMatrix(camera.combined);
            Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
        }



        if(viewAble) {
            updateWorld(detTime);
        }else{
            int tmp=100;
            while(!updateWorld(detTime)&&tmp--!=0);
        }



        // game
        batch.begin();

        batch.end();

        if(viewAble) {
//
            box2DDebugRenderer.render(world, camera.combined);

            //UI
            batch.setProjectionMatrix(UIcamera.combined );
            batch.begin();

            batch.end();
        }
    }

    @Override
    public void pause () {
        super.pause();
    }

    @Override
    public void resume () {
        super.resume();
    }

    @Override
    public void dispose () {
        super.dispose();
        batch.dispose();
        shapeRenderer.dispose();
        core.dispose();
        box2DDebugRenderer.dispose();
    }
}
